import os
import pickle
import logging
import logging.handlers
import socketserver
import struct
import socket
from .logger import LocalLogger
from .ctips import ctip

LOG_DIR = './logs'
LOG_LEV = 'debug'


class LogRecordStreamHandler(socketserver.StreamRequestHandler):
    """Handler for a streaming logging request.

    This basically logs the record using whatever logging policy is
    configured locally.
    """

    def handle(self):
        """
        Handle multiple requests - each expected to be a 4-byte length,
        followed by the LogRecord in pickle format. Logs the record
        according to whatever policy is configured locally.
        """
        while True:
            # 接收数据的流程
            chunk = self.connection.recv(4)
            if len(chunk) < 4:
                break
            slen = struct.unpack('>L', chunk)[0]
            chunk = self.connection.recv(slen)
            while len(chunk) < slen:
                chunk = chunk + self.connection.recv(slen - len(chunk))
            obj = self.unPickle(chunk)
            # 生成LodRecord实例，调用handleLogRecord处理
            record = logging.makeLogRecord(obj)
            self.handleLogRecord(record)

    def unPickle(self, data):
        return pickle.loads(data)

    def handleLogRecord(self, record):
        # if a name is specified, we use the named logger rather than the one
        # implied by the record.
        if self.server.logname is not None:
            name = self.server.logname
        else:
            name = record.name
        #logger = logging.getLogger(name)
        # N.B. EVERY record gets logged. This is because Logger.handle
        # is normally called AFTER logger-level filtering. If you want
        # to do filtering, do it at the client end to save wasting
        # cycles and network bandwidth!
        #logger.handle(record)

        logger = LocalLogger(log_path=LOG_DIR, app_name=name, write_level=LOG_LEV, show_info=False)

        # print(dir(record), type(record))
        logger.info(record.msg)



class LogRecordSocketReceiver(socketserver.ThreadingTCPServer):
    """
    Simple TCP socket-based logging receiver suitable for testing.
    """

    allow_reuse_address = True

    def __init__(self, host='localhost',
                 port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
                 handler=LogRecordStreamHandler):
        socketserver.ThreadingTCPServer.__init__(self, (host, port), handler)
        self.abort = 0
        self.timeout = 3
        self.logname = None

    def serve_until_stopped(self):
        import select
        abort = 0
        while not abort:
            # select方法接收端口数据
            rd, wr, ex = select.select([self.socket.fileno()],
                                       [], [],
                                       self.timeout)
            if rd:
                # 调用LogRecordStreamHandler的handle方法处理
                self.handle_request()
            abort = self.abort

def do_server(log_dir='./logs', log_lev='debug', host='localhost', port=logging.handlers.DEFAULT_TCP_LOGGING_PORT):
    global LOG_DIR
    global LOG_LEV

    LOG_DIR = log_dir
    LOG_LEV = log_lev

    def check_port(ip, port=80):
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        try:
            s.connect((ip, port))
            s.shutdown(2)
            print('%s:%d is used' % (ip, port))
            return True
        except socket.error as e:
            print('%s:%d is unused' % (ip, port))
            return False

    if check_port(host, port):
        raise ConnectionError("{}:{} port {} has been occupied. please use another port...".format(host, port, port))
    tcpserver = LogRecordSocketReceiver(host=host, port=port)
    ctip('Start Visual Analysis Logger Server [pid:%d]...' % (os.getpid()), show=True)
    tcpserver.serve_until_stopped()
    